<?php
/**
 * Class for handle all information aboult price caculation.
 *
 * @access 	public
 * @author 	Valentin
 * @copyright	ResMania 2009 all rights reserved.
 * @version	1.0
 * @link		http://developer.resmania.com/api
 * @since  	05-2009
 */
class RM_HourlyPrices_Calculator {
    /**
     * @var RM_HourlyUnitPrices
     */
    protected $_unitPricesModel;

    /**
     * @var RM_UnitPricesConfig
     */
    protected $_unitPricesConfigModel;

    /**
     * @var Zend_Translate
     */
    protected $_translate;

    /**
     * Constructor
     *
     * @param RM_HourlyUnitPrices $unitPricesModel
     * @param RM_UnitHourlyPricesConfig $unitPricesConfigModel
     * @param Zend_Translate $translate
     */
    public function  __construct($unitPricesModel, $unitPricesConfigModel, $translate) {
        $this->_unitPricesModel = $unitPricesModel;
        $this->_unitPricesConfigModel = $unitPricesConfigModel;
        $this->_translate = $translate;
    }

    /**
     * Calculate total price for one unit
     *
     * @param RM_HourlyPrices_Information $information
     * @param bool $byStep - if true, the result will be in array (0 => array('step' => RM_Date, 'price' => float))
     */
    public function getTotalUnitPrice($information, $byStep = false) {
        $hours = $information->getPeriod()->getHours();
        $price = 0;
        $total = 0;
        $totalHours = array();
        $duration = count($hours);
        foreach ($hours as $hour) {
            $price = $this->getPrice(
                $hour,
                $duration,
                $information->getUnit(),
                $information->getPersons()
            );
            if ($byStep) {
                $totalHours[] = array('step' => clone $hour, 'price' => RM_Environment::getInstance()->roundPrice($price));
            } else {
                $total += $price;
            }
        }
        if ($byStep) {
            return $totalHours;
        } else {
            return RM_Environment::getInstance()->roundPrice($total);
        }
    }

    /**
     * Return price for one day. Based on weekday rate or weekend rate or week price (substracting by 7)
     *
     * @param RM_Date $hour
     * @param int $duration Total duration in hours
     * @param Zend_Db_Table_Row_Abstract $unit Unit that belong to reservation
     * @param int $persons Number of persons that will live in unit
     *
     * @return float
     */
    public function getPrice($hour, $duration, $unit, $persons) {
        $model = $this->_unitPricesModel;
        $priceRow = $model->getByHour($unit, $hour, $persons);
        if ($priceRow == null) {
            return 0;
        }

        // min stay == max stay
        if ((int)$priceRow->min !==0 && (int)$priceRow->max !==0 && ((int)$priceRow->min === (int)$priceRow->max)){
            if ($daysNumber > (int)$priceRow->max || $daysNumber < (int)$priceRow->min){
                $msg = str_replace("[XX]", $priceRow->max, $this->_translate->_('RM.Module.DailyPrices', 'DaysRetrictedTo'));
                throw new RM_Exception($msg);
            }
        }

        // min stay check
        if ($duration < (int)$priceRow->min) {
            $msg = str_replace("[XX]",$priceRow->min,$this->_translate->_('RM.Module.HourlyPrices', 'DaysNumberIsSmallerThanMin'));
            throw new RM_Exception($msg);
        }

        // max stay check
        if ((int)$priceRow->max !== 0 && (((int)$priceRow->max >= (int)$priceRow->min) && ($duration > (int)$priceRow->max))) {
            $msg = str_replace("[XX]",$priceRow->max,$this->_translate->_('RM.Module.HourlyPrices', 'DaysNumberIsGreaterThanMax'));
            throw new RM_Exception($msg);
        }

        $priceConfigModel = $this->_unitPricesConfigModel;
        $weekendPriceEnabled = $priceConfigModel->fetchValueByUnit($unit->id, 'weekend_price_enabled');
        if ($weekendPriceEnabled) {
            $weekendDays = $priceConfigModel->fetchValueByUnit($unit->id, 'weekend_days');
            $weekendStartHour = $priceConfigModel->fetchValueByUnit($unit->id, 'weekend_start');
            $weekendEndHour = $priceConfigModel->fetchValueByUnit($unit->id, 'weekend_end');
            if (RM_HourlyPrices_Weekend::isWeekend($weekendDays, $weekendStartHour, $weekendEndHour, $hour)) {
                return $priceRow->weekend;
            }
        }

        if ($duration < 4) {
            return $priceRow->hour;
        }
        if ($duration < 8) {
            return $priceRow->hours4;
        }
        if ($duration < 24) {
            return $priceRow->hours8;
        }
        if ($duration < 168) {
            return $priceRow->day;
        }
        return $priceRow->week;
    }
}